package org.ricks.net.action;

import org.ricks.ioc.TaskBus;
import org.ricks.ioc.event.*;
import org.ricks.ioc.utils.Logger;
import org.ricks.net.action.context.FlowContext;
import org.ricks.net.action.context.head.HeadMeta;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;

import java.util.concurrent.*;

public class ActionBus {
    private static final Map<Integer, ActionReceiver> receiverMap = new ConcurrentHashMap<>();
    private static volatile TripleConsumer<ActionReceiver, FlowContext, Throwable> exceptionHandler;
    private static volatile Consumer<Integer> noHandlerHandler;

    // 优化10: 使用虚拟线程执行器
    private static final Executor virtualThreadExecutor = Executors.newThreadPerTaskExecutor(
            Thread.ofVirtual().name("action-handler-", 0).factory()
    );

    static {
        setDefaultHandlers();
    }

    private static void setDefaultHandlers() {
        exceptionHandler = (handler, context, ex) -> {
            Logger.debug("Unhandled exception in handler: {}",ex, handler);
            if (context.headMeta.isRpc() && !context.headMeta.isRpcResponse()) {
                context.rpcError(500, "Server Error");
            }
        };

        noHandlerHandler = command -> Logger.debug("No handler registered for command: {}", command);
    }

    public static void handlerAction(int taskExecutorHash, FlowContext<? extends HeadMeta> context) {
        Objects.requireNonNull(context, "Context cannot be null");

        ActionReceiver receiver = receiverMap.get(context.getCommand());
        if (receiver == null) {
            noHandlerHandler.accept(context.getCommand());
            return;
        }

        switch (receiver.task()) {
            case TaskBus -> TaskBus.execute(taskExecutorHash, () -> safeExecute(receiver, context));
            case EventBus -> EventBus.asyncExecute(taskExecutorHash, () -> safeExecute(receiver, context));
            case VirtualThread -> virtualThreadExecutor.execute(() -> safeExecute(receiver, context));
        }
    }

    private static void safeExecute(ActionReceiver receiver, FlowContext<?> context) {
        try {
            receiver.invoke(context);
        } catch (Throwable t) {
            handleException(receiver, context, t);
        }
    }

    private static void handleException(ActionReceiver handler, FlowContext context, Throwable ex) {
        try {
            exceptionHandler.accept(handler, context, ex);
        } catch (Exception handlerEx) {
            Logger.error("Exception handler failed", handlerEx);
        }
        EventBus.post(new ActionExceptionEvent(handler, context, ex));
    }

    public static void registerReceiver(int cmd, ActionReceiver receiver) {
        receiverMap.put(cmd, receiver);
    }

    public static void configure(TripleConsumer<ActionReceiver, FlowContext, Throwable> exceptionHandler,
                                 Consumer<Integer> noHandlerHandler) {
        ActionBus.exceptionHandler = Objects.requireNonNull(exceptionHandler);
        ActionBus.noHandlerHandler = Objects.requireNonNull(noHandlerHandler);
    }
}